package oo

import (
	"elegantGo/chapter17/controller/response"
	"elegantGo/chapter17/oo/article"
	"elegantGo/chapter17/oo/primitive"
)

type ArticleContentMasker interface {
	Mask()
}

type Articles []Article

type Article interface {
	GetID() int
	SetID(id int)
	GetCategory() int
	SetCategory(v int)
	GetTitle() string
	SetTitle(v string)
	GetSummary() string
	SetSummary(v string)
	GetReadCount() int
	SetReadCount(v int)
	GetContent() string
	SetContent(v string)
	GetUser() User
	SetUser(v User)

	Mapper() *response.Article
	MapperWithMask(fieldMask *FieldMask) *response.Article
}

func NewArticle(category int) Article {
	var trait Article
	switch category {
	case article.CategoryFree:
		trait = &FreeArticle{}
	case article.CategoryPaid:
		trait = &PaidArticle{}
	case article.CategoryVip:
		trait = &VipArticle{}
	}
	trait.SetCategory(category)

	return trait
}

func (oo Articles) MapperWithMask(fieldMask *FieldMask) response.Articles {
	size := len(oo)
	respArticles := make(response.Articles, size)
	for i := 0; i < size; i++ {
		respArticles[i] = oo[i].MapperWithMask(fieldMask)
	}

	return respArticles
}

func (oo Articles) Mapper() response.Articles {
	size := len(oo)
	respArticles := make(response.Articles, size)
	for i := 0; i < size; i++ {
		respArticles[i] = oo[i].Mapper()
	}
	return respArticles
}

type baseArticle struct {
	id        primitive.ID
	category  article.Category
	title     article.Title
	summary   article.Summary
	readCount article.ReadCount

	user User
}

func (oo *baseArticle) GetID() int {
	return oo.id.Value()
}

func (oo *baseArticle) SetID(v int) {
	oo.id.SetValue(v)
}

func (oo *baseArticle) GetCategory() int {
	return oo.category.Value()
}

func (oo *baseArticle) SetCategory(v int) {
	oo.category.SetValue(v)
}

func (oo *baseArticle) GetTitle() string {
	return oo.title.Value()
}

func (oo *baseArticle) SetTitle(v string) {
	oo.title.SetValue(v)
}

func (oo *baseArticle) GetSummary() string {
	return oo.title.Value()
}

func (oo *baseArticle) SetSummary(v string) {
	oo.title.SetValue(v)
}

func (oo *baseArticle) GetReadCount() int {
	return oo.readCount.Value()
}

func (oo *baseArticle) SetReadCount(v int) {
	oo.readCount.SetValue(v)
}

func (oo *baseArticle) GetUser() User {
	return oo.user
}

func (oo *baseArticle) SetUser(v User) {
	oo.user = v
}

func (oo *baseArticle) MapperWithMask(fieldMask *FieldMask) *response.Article {
	if oo == nil {
		return nil
	}
	respArticle := new(response.Article)
	respArticle.ID = oo.id.Value()
	respArticle.Category = oo.category.Value()
	respArticle.Title = oo.title.Value()
	respArticle.Summary = oo.summary.Value()
	respArticle.ReadCount = oo.readCount.Value()

	if oo.user != nil {
		respArticle.User = oo.user.Mapper()
	}

	//fmt.Println(fieldMask.String())

	distArticle := new(response.Article)
	fieldMask.Copy(respArticle, distArticle)

	return distArticle
}

func (oo *baseArticle) Mapper() *response.Article {
	if oo == nil {
		return nil
	}
	respArticle := new(response.Article)
	respArticle.ID = oo.id.Value()
	respArticle.Category = oo.category.Value()
	respArticle.Title = oo.title.Value()
	respArticle.Summary = oo.summary.Value()
	respArticle.ReadCount = oo.readCount.Value()

	if oo.user != nil {
		respArticle.User = oo.user.Mapper()
	}

	return respArticle
}
